﻿using NewsSystem.Contracts;
using NewsSystem.Models;
using System;
using System.Collections.Generic;
using System.Data.Entity;

namespace NewsSystem.Repositories
{
    public class NewsSystemUnitOfWork : INewsUnitOfWork, IDisposable
    {
        private readonly DbContext dbContext;
        private readonly IDictionary<Type, object> repositories;

        public NewsSystemUnitOfWork(DbContext context)
        {
            this.dbContext = context;
            this.repositories = new Dictionary<Type, object>();
        }

        public IRepository<Article> Article
        {
            get
            {
                return this.GetRepository<BaseRepository<Article>>();
            }
        }

        public IUserRepository User
        {
            get
            {
                return this.GetRepository<UsersRepository>();
            }
        }

        public IRepository<Comment> Comment
        {
            get
            {
                return this.GetRepository<BaseRepository<Comment>>();
            }
        }

        public IRepository<Vote> Vote
        {
            get
            {
                return this.GetRepository<BaseRepository<Vote>>();
            }
        }

        public IRepository<Image> Image
        {
            get
            {
                return this.GetRepository<BaseRepository<Image>>();
            }
        }


        public void Commit()
        {
            this.dbContext.SaveChanges();
        }

        private T GetRepository<T>() 
            where T: class
        {
            var type = typeof(T);
            if (this.repositories.ContainsKey(type))
            {
                return this.repositories[type] as T;
            }

            return this.CreateRepository(type) as T;
        }

        private object CreateRepository(Type type)
        {
            var instance = Activator.CreateInstance(type, this.dbContext);
            this.repositories[type] = instance;
            return instance;
        }

        public void Dispose()
        {
            if (this.dbContext != null)
            {
                this.dbContext.Dispose();
            }

            GC.SuppressFinalize(this);
        }
    }
}
